﻿using System;
using System.Collections.Generic;
using System.IO;
using TpsAutoSurvey_PDA_Version_.RealizedClasses;
using System.Text;
using System.Collections;
using System.Threading;
using System.Reflection;
using TpsAutoSurvey_PDA_Version_.SocketModule;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace TpsAutoSurvey_PDA_Version_.Presenter
{

   
    public class SurveyTpsController:SurveyBase
    {
        GeoCom geocom { get; set; }
        svtps mytps { get; set; }
        int StationId { get; set; }
        public override event EventHandler OnerrHappen;
        public override event EventHandler OnSurveyComplete;
        public SurveyTpsController():base()
        {
           
        }


        public override void MsgCome(SendData data)
        {
            if (data.Data.Command == "GetAllPoints")
            {
                string[] array = new string[this.mytps.ConfigPoints.Count];
                for (int i = 0; i < this.mytps.ConfigPoints.Count; i++)
                {
                    array[i] = this.mytps.ConfigPoints[i].name;
                }
                SendToTcpServer("Command", "GetAllPoints", array);
            }
            else if (data.Data.Command == "StartSurvey")
            {
                if (this.IsWorking == false)
                {
                    SendToTcpServer("Message", "", "测量指令已下达,等待仪器执行........");
                    try
                    {
                        JContainer ct = data.Data.Para as JContainer;
                        List<string> names = new List<string>();
                        foreach (var value in ct.AsJEnumerable())
                        {

                            names.Add(JsonConvert.DeserializeObject(value.ToString()).ToString());
                        }
                        //将mytps 的points备份并更改
                        this.mytps.ApplyFilterPoints(names);
                    }
                    catch
                    {
                        this.mytps.ClonePoints();
                    }
                    this.StartSurvey(new CommandPara("", ""));
                }
                else
                {
                    SendToTcpServer("Message", "", "正在执行测量任务");
                }
            }
            else if (data.Data.Command == "StopSurvey")
            {
                this.StopSurvey();
                SendToTcpServer("Message", "", "停止指令已下达,等待全站仪执行.........");
            }

        }

        void mytimer_SurveyTimeup(object sender, EventArgs e)
        {
            if (this.IsWorking == true)
            {
                return;
            }
            this.StartSurvey();
        }
  
        private void GetMeasureSvpoint(int turnIndex, int ptIndex)
        {
            SendToTcpServer("Message", "", "观测:" + mytps.points[ptIndex].name);
            svpoint p = GetMeasureSvpointFrmGeocom(ptIndex);

            if (mytps.curface == Face.face1)
            {
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].Hz1 = p.Hz1;
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].Hv1 = p.Hv1;
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].slope1 = p.slope1;
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].time1 = p.time1;
                
            }
            else
            {
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].Hz2 = p.Hz1;
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].Hv2 = p.Hv1;
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].slope2 = p.slope1;
                mytps.myturn.turn_list[turnIndex].pts[ptIndex].time2 = p.time1;
            }

            if (p.slope1 == 0)
            {
                mytps.myturn.turn_list[turnIndex].unsurvey.Add(ptIndex);

            }
            else
            {
                var ppp = mytps.PolarToXYZ(p.Hz1, p.Hv1, p.slope1);
                string result = string.Format("E:{0}    N:{1}   H:{2}", ppp.E, ppp.N, ppp.H);
                SendToTcpServer("Message", "", result);
            }
        }
        
        //测量,并获取点
        private svpoint GetMeasureSvpointFrmGeocom(int ptIndex)
        {
            try
            {
                MakePostionCmd(ptIndex);
                string str = geocom.Measure_Distance_Angle();
                Thread.Sleep(1000);
                svpoint p = new svpoint();
                p.time1 = DateTime.Now;
                if (!str.Equals("0"))
                {
                    string[] v = str.Split(',');
                    p.Hz1 = Convert.ToDouble(v[0]);
                    p.Hv1 = Convert.ToDouble(v[1]);
                    p.slope1 = Convert.ToDouble(v[2]);
                    if (mytps.check_legal(p.slope1, ptIndex) == true)
                    {
                        return p;
                    }
                    else
                    {
                        SendToTcpServer("Message", "", "与学习点差别过大,放弃..");
                        p = new svpoint();
                        p.time1 = DateTime.Now;
                    }
                }
                return p;
            }
            catch (Exception a)
            {
                svpoint p = new svpoint();
                p.time1 = DateTime.Now;
                SendToTcpServer("Message", "", "测量失败....");
                ToolClass.Log(a.Message);
                return p;
            }

        }
        //转向
        private void MakePostionCmd(int ptIndex)
        {
            double hz = mytps.getAzim(ptIndex);
            double hv = mytps.getVertA(ptIndex);
            string cmd = hz.ToString() + "," + hv.ToString();
            geocom.Make_Postion(cmd);
            Thread.Sleep(300);
        }

      
        void one_turn_survey(int turnIndex)
        {
            mytps.myturn.turn_list[turnIndex].unsurvey = new List<int>();

            //先正镜或倒镜测量一遍
            for (int j = 0; j < mytps.points.Count; j++)
            {
                GetMeasureSvpoint(turnIndex, j);
            }
            int[] un = mytps.myturn.turn_list[turnIndex].unsurvey.ToArray();
            //补测
            if (un.Length > 0)
            {
                SendToTcpServer("Message", "", "补测..........");
                Thread.Sleep(500);
            }
            for (int j = 0; j < un.Length; j++)
            {
                GetMeasureSvpoint(turnIndex, un[j]);
            }
        }

        private void take_turns(bool IsOrientationAdded)
        {
            //重新定向
            //ReOrientation();
            mytps.curface = Face.face1;
            //如果观测方向大于等于4,则需要归零,于是就加上第一个零方向点
            if (mytps.points.Count >= 4 && IsOrientationAdded == true)
            {
                mytps.points.Add(mytps.points[0]);
            }
            mytps.FillEmptyData(datatrans.turnNo);


            //开始测回观测
            for (int i = 0; i < mytps.myturn.Count; i++)
            {

                mytps.curface = Face.face1;
                SendToTcpServer("Message", "", "开始正镜测量..........");
                one_turn_survey(i);
                mytps.curface = Face.face2;
                Thread.Sleep(500);
                SendToTcpServer("Message", "", "开始倒镜测量..........");
                one_turn_survey(i);
                //在这里归零,检核,等等操作
                string msg = "";
                mytps.myturn.turn_list[i].check(ref msg, mytps.zeroangle, IsOrientationAdded);
            }
            geocom.Make_Postion(mytps.zeroangle + ",3.1415926");
            mytps.curface = Face.face1;
        }




        //重新定向为0
        public bool ReOrientation()
        {
            try
            {
                mytps.curface = Face.face1;
                svpoint p = GetMeasureSvpointFrmGeocom(0);
                if (mytps.check_legal(p.slope1, 0) == false)
                {
                    return false;
                }
                geocom.Set_Orientaion(mytps.zeroangle.ToString());
                return true;
            }
            catch (Exception a)
            {
                ToolClass.Log(a.Message);
                return false;
            }
        }



        //自动观测的时候使用
        protected override void AutomaticSurvey()
        {
            if (CheckGeoCom())
            {
                IsWorking = true;
                Survey();
                IsWorking = false;
            }
        }
        //人工操作测量
        protected override void ManualSurvey()
        {
            if (CheckGeoCom())
            {
                IsWorking = true;
                Survey();
                IsWorking = false;
            }
        }
        private bool CheckGeoCom()
        {
            if (geocom == null ||
               geocom.port == null ||
               geocom.port.IsOpen == false)
            {
                para.result = "没有打开串口!";
                if (OnerrHappen != null)
                {
                    OnerrHappen(para, new EventArgs());
                }
                ToolClass.Log("没有打开串口!");
                SendToTcpServer("Message", "", "没有打开串口,测量任务已终止!");
                this.IsWorking = false;
                return false;
            }
            return true;
        }
        private void Survey()
        {
            try
            {

                take_turns(true);
                ResultData[] data = mytps.get_xyz();
                List<svpoint> pts = mytps.myturn.turn_list[0].pts;
                SendToTcpServer("Message", "", "测量完成,等待全站仪传输测量结果..........");
                try
                {
                    
                    curTimeNo = datatrans.GetCurNo;
                    //datatrans.SavePointsInLocalDataBase(pts, curTimeNo);
                    datatrans.SavePointsInRemoteDataBase(data, curTimeNo);
                }
                catch(Exception a)
                {
                    SendToTcpServer("Message", "", "远程数据库传输出现问题,测量完成但数据未上传!");
                    if (OnerrHappen != null)
                    {
                        para.result = "远程传输出现问题,测量完成但数据未上传!\r\n错误信息:" + a.Message;
                        OnerrHappen(para, new EventArgs());
                    }
                    return;
                }
                if (OnSurveyComplete != null && para.Sender.Length > 0)
                {
                    para.result = "测量完成!";
                    OnSurveyComplete(para, new EventArgs());
                }
                SendToTcpServer("Command", "SurveyComplete", "");
                return;
            }
            catch (Exception a)
            {
                if (a.GetType() == typeof(ThreadAbortException))
                {
                    SendToTcpServer("Message", "", "测量已成功被终止!");
                    if (OnSurveyComplete != null)
                    {
                        para.result = "测量已成功被终止!";
                        OnSurveyComplete(para, new EventArgs());
                    }
                    
                    return;
                }
                ToolClass.Log(a.Message);
                if (OnerrHappen != null)
                {
                    para.result = a.Message;
                    OnerrHappen(para, new EventArgs());
                }
                return;
            }
        }

        #region 公共方法

        [DescriptionAttribute("重置")]
        public override CommandPara PrepareStation(CommandPara p)
        {
            try
            {
                IsWorking = false;
                if (geocom != null && geocom.port.IsOpen == true)
                {
                    geocom.port.Close();
                }
                datatrans = new DataTransmission();
                geocom = datatrans.Geo;
                mytps = datatrans.MySvtps;
                mytps.ConfigPoints = datatrans.GetConfigPoints();
                //curTimeNo = datatrans.GetCurNo;
                if (mytps.points.Count == 0)
                {
                    ToolClass.Log("获取学习点失败!");
                    p.result = "获取学习点失败!";
                    return p;
                }
                return p;
            }
            catch (Exception a)
            {
                ToolClass.Log(a.Message);
                p.result = "重置失败," + a.Message;
                return p;
            }
        }

        [DescriptionAttribute("测试连接")]
        public override CommandPara IsTPSConnected(CommandPara p)
        {
            string tpscoor = geocom.Get_Station();
            if (tpscoor != "0" && tpscoor != "")
            {
                return p;
            }
            else
            {
                p.result = "测试连接失败!";
                return p;
            }
        }
        [DescriptionAttribute("关机")]
        public override CommandPara ShutDown(CommandPara p)
        {
            if ( geocom.Shut_Off()!="0")
            {
                return p;
            }
            else
            {
                p.result = "关机失败!";
                return p;
            }
        }
        #endregion
    }

    public class DescriptionAttribute:Attribute
    {
        public DescriptionAttribute(string Descrition_in) 
        {
            this.description = Descrition_in; 
        }
        protected String description;
        public String Description
        {
            get
            {
                return this.description;
                
            }
        }
    }

    public enum ResultTip
    {
        正在测量中,
        遇到错误,
        测量结束,
        重置完成,
        未识别的命令,
        没有打开串口
    }

    public class CommandPara
    {
        public string Sender { get; set; }
        public string result { get; set; }
        public string MethedInfo { get; set; }
        public CommandPara(string s, string m)
        {
            Sender = s;
            result = m + "成功";
            MethedInfo = m;
        }
        public CommandPara(string s, string m,string r)
        {
            Sender = s;
            result = m;
            MethedInfo = m;
            result = r;
 
        }
    }
}
